package cn.virens.oauth.permission;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.virens.common.exception.APIException;
import cn.virens.common.utils.StreamUtil;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@SuppressWarnings("serial")
public class VirensPermission implements Serializable {
    private static final Map<String, VirensPermission> cache = new ConcurrentHashMap<>();

    protected static final String WILDCARD = "*";

    private final List<Set<String>> parts;

    private VirensPermission(String actions) {
        this.parts = pasre(actions);
    }

    /**
     * 权限匹配(满足任一条件即可)
     */
    public boolean implies(String... permissionArr) throws APIException {
        if (permissionArr != null && permissionArr.length >= 1) {
            for (String permission : permissionArr) {
                if (implies(resolve(permission))) {
                    return true;//
                }
            }

            return false;
        } else {
            return true;
        }
    }

    /**
     * 权限匹配<br>
     * a:b--a:b:v => true<br>
     * a:b:c--a:b => false<br>
     * a:b:*--a:b:v => true<br>
     * a:b:v--a:b:v => true<br>
     * a:b:v--a:b:u => false<br>
     * a:b:v,m--a:b:v => true<br>
     * a:b:v,m--a:b:u => false<br>
     */
    public boolean implies(VirensPermission other) throws APIException {
        if (parts.size() > other.parts.size()) return false;

        for (int i = 0; i < parts.size(); i++) {
            Set<String> ov = other.getNode(i);
            Set<String> tv = this.getNode(i);

            if (!v(tv, ov)) return false;
        }

        return true;
    }

    /**
     * 获取指定节点的权限信息
     */
    private Set<String> getNode(int i) throws APIException {
        if (0 <= i && i < parts.size()) {
            return parts.get(i);
        } else {
            return null;
        }
    }

    @Override
    public String toString() throws APIException {
        return StreamUtil.stream(parts).map(s -> {
            return CollUtil.join(s, ",");
        }).collect(Collectors.joining(":"));
    }

    /**
     * 根据权限标识获取权限对象，如果不存在就进行解析
     */
    public static VirensPermission resolve(String actions) throws APIException {
        return cache.computeIfAbsent(actions, VirensPermission::new);
    }

    /**
     * 权限字符串分隔
     */
    private static List<Set<String>> pasre(String permissionStr) throws APIException {
        return StreamUtil.stream(split(permissionStr, ":")).map(a -> {
            return StreamUtil.stream(split(a, ",")).filter(c -> {
                return c != null && !c.isEmpty();
            }).collect(Collectors.toSet());
        }).collect(Collectors.toList());
    }

    /**
     * 权限匹配,判断this中是否完全包含other权限
     *
     * @param set1 this的权限节点
     * @param set2 other的权限节点
     * @return
     */
    private static boolean v(Set<String> set1, Set<String> set2) {
        if (set1 == null || !set1.contains(WILDCARD)) {
            return CollUtil.containsAll(set1, set2);
        } else {
            return true;
        }
    }

    private static List<String> split(String string, String c) {
        if (string != null && !string.isEmpty()) {
            return StrUtil.split(string, c);
        } else {
            return Collections.emptyList();
        }
    }

}
